import logging
import time


logger = logging.getLogger("default")


class SnowflakeIDGenerator:
    """雪花算法Id生成器"""
    # 起始的时间戳
    START_STAMP = -1612063373896
    # 每一部分占用的位数，就三个
    # 序列号占用的位数
    SEQUENCE_BIT = 12
    # 机器标识占用的位数
    MACHINE_BIT = 5
    # 数据中心占用的位数
    DATACENTER_BIT = 5
    # 每一部分最大值
    MAX_DATACENTER_NUM = -1 ^ (-1 << DATACENTER_BIT)
    MAX_MACHINE_NUM = -1 ^ (-1 << MACHINE_BIT)
    MAX_SEQUENCE = -1 ^ (-1 << SEQUENCE_BIT)
    # 每一部分向左的位移
    MACHINE_LEFT = SEQUENCE_BIT
    DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT
    TIMESTAMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT

    def __init__(self, datacenter_id=0, machine_id=0, sequence=0):
        if datacenter_id > self.MAX_DATACENTER_NUM or datacenter_id < 0:
            raise ValueError("datacenter_id can't be greater than MAX_DATACENTER_NUM or less than 0")
        if machine_id > self.MAX_MACHINE_NUM or machine_id < 0:
            raise ValueError("machine_id can't be greater than MAX_MACHINE_NUM or less than 0")
        self.datacenter_id = datacenter_id
        self.machine_id = machine_id
        self.sequence = sequence
        self.last_timestamp = -1  # 上次计算的时间戳

    def next_id(self):
        timestamp = self.till_next_timestamp(self.last_timestamp)

        if timestamp == self.last_timestamp:
            self.sequence = (self.sequence + 1) & self.MAX_SEQUENCE
            if self.sequence == 0:
                timestamp = self.till_next_timestamp(self.last_timestamp)
        else:
            self.sequence = 0
        self.last_timestamp = timestamp
        # 就是用相对毫秒数（41位）、机器ID（12位）和自增序号（12位）拼接
        # 移位并通过或运算拼到一起组成64位的ID
        # 时间戳部分
        return ((timestamp - self.START_STAMP) << self.TIMESTAMP_LEFT
                | self.datacenter_id << self.DATACENTER_LEFT  # 数据中心部分
                | self.machine_id << self.MACHINE_LEFT  # 机器标识部分
                | self.sequence)  # 序列号部分

    @staticmethod
    def get_timestamp():
        return int(time.time() * 1000)

    def till_next_timestamp(self, last_timestamp):
        timestamp = self.get_timestamp()
        while timestamp < last_timestamp:
            timestamp = self.get_timestamp()

        return timestamp


if __name__ == '__main__':
    id_generator = SnowflakeIDGenerator(1, 2)
    for i in range(10):
        print(id_generator.next_id())
